package com.general.framework.cc.limit;

import com.google.common.util.concurrent.RateLimiter;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class MethodLimitAOP {
    @Before("execution(@MethodLimitAnno * *(..))")
    public void limit(JoinPoint joinPoint){
        // 1. 从joinPoint里面获取当前调用的方法
        Method method = getNowMethod(joinPoint);

        // 2. 从方法定义上，获取@MethodLimitAnno注解，取出里面的 limitType 参数
        if (method != null){
            String limitType = method.getAnnotation(MethodLimitAnno.class).limitType();
            // 3. 使用令牌桶算法，来获取令牌，如果获取不到，会在这里等
            RateLimiter rateLimiter = LimitHelper.getRateLimiter(limitType);
            rateLimiter.acquire();
        }
    }

    /**
     * 获取当前调用的方法
     * @param joinPoint
     * @return
     */
    private Method getNowMethod(JoinPoint joinPoint){
        // 通过反射获取 target 对象中的 method
        Method[] methods = joinPoint.getTarget().getClass().getMethods();

        // 判断当前调用的方法名是否与 target 对象中的方法名一致
        Method method = null;
        for (Method mth : methods) {
            if(mth.getName().equals(joinPoint.getSignature().getName())){
                method = mth;
                break;
            }
        }
        return method;
    }
}
